home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 2: CDPD 1
/
Almathera Ten on Ten - Disc 2: CDPD 1.iso
/
pd
/
076-100
/
092
/
bawk
/
bawkdo.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-13
|
10KB
|
477 lines
/*
* Bawk C actions interpreter
*/
#include <stdio.h>
#include "bawk.h"
static char pop_array[MAX_TOKEN + 1];
void init_pop_array()
{
register int i;
DBUG_ENTER("init_pop_array");
for(i = 0; i <= MAX_TOKEN; i++)
pop_array[i] = 1;
pop_array[T_STATEMENT] = pop_array[T_IF] = pop_array[T_DECLARE] = 0;
pop_array[T_DECLARE] = pop_array[T_ARRAY_DECLARE] = 0;
pop_array[T_BREAK] = 0;
DBUG_VOID_RETURN;
}
int dopattern( root )
register EXPR_NODE *root;
{
DBUG_ENTER("dopattern");
Where = PATTERN;
walk_tree(root);
DBUG_RETURN(popint());
}
void doaction( root )
register EXPR_NODE *root;
{
DBUG_ENTER("doaction");
Where = ACTION;
walk_tree(root);
DBUG_VOID_RETURN;
}
void walk_tree(root)
register EXPR_NODE *root;
{
register int ival;
DATUM data;
register VARIABLE *pvar;
register VARDECL *pdecl;
DBUG_ENTER("walk_tree");
if(Saw_break || !root)
DBUG_VOID_RETURN;
switch(root->operator) {
case T_ASSIGN:
walk_tree(root->left);
walk_tree(root->right);
assignment();
break;
case T_LOR:
walk_tree(root->left);
if(popint())
pushint(1);
else {
walk_tree(root->right);
pushint(popint() != 0);
}
break;
case T_LAND:
walk_tree(root->left);
if(!popint())
pushint(0);
else {
walk_tree(root->right);
pushint(popint() != 0);
}
break;
case T_OR:
walk_tree(root->left);
walk_tree(root->right);
pushint(popint() | popint());
break;
case T_AND:
walk_tree(root->left);
walk_tree(root->right);
pushint(popint() & popint());
break;
case T_XOR:
walk_tree(root->left);
walk_tree(root->right);
pushint(popint() ^ popint());
break;
case T_EQ:
walk_tree(root->left);
walk_tree(root->right);
pushint(popint() == popint());
break;
case T_NE:
walk_tree(root->left);
walk_tree(root->right);
pushint(popint() != popint());
break;
case T_LE:
walk_tree(root->left);
ival = popint();
walk_tree(root->right);
pushint(ival <= popint());
break;
case T_GE:
walk_tree(root->left);
ival = popint();
walk_tree(root->right);
pushint(ival >= popint());
break;
case T_LT:
walk_tree(root->left);
ival = popint();
walk_tree(root->right);
pushint(ival < popint());
break;
case T_GT:
walk_tree(root->left);
ival = popint();
walk_tree(root->right);
pushint(ival > popint());
break;
case T_SHL:
walk_tree(root->left);
ival = popint();
walk_tree(root->right);
pushint(ival << popint());
break;
case T_SHR:
walk_tree(root->left);
ival = popint();
walk_tree(root->right);
pushint(ival >> popint());
break;
case T_ADD:
walk_tree(root->left);
walk_tree(root->right);
pushint(popint() + popint());
break;
case T_SUB:
walk_tree(root->left);
ival = popint();
walk_tree(root->right);
pushint(ival - popint());
break;
case T_MUL:
walk_tree(root->left);
ival = popint();
walk_tree(root->right);
pushint(ival * popint());
break;
case T_DIV:
walk_tree(root->left);
ival = popint();
walk_tree(root->right);
pushint(ival / popint());
break;
case T_MOD:
walk_tree(root->left);
ival = popint();
walk_tree(root->right);
pushint(ival % popint());
break;
case T_LNOT:
walk_tree(root->left);
pushint( ! popint() );
break;
case T_NOT:
walk_tree(root->left);
pushint( ~ popint() );
break;
case T_INCR:
walk_tree(root->left);
preincdec(1);
break;
case T_DECR:
walk_tree(root->left);
preincdec(-1);
break;
case T_DOLLAR:
/*
* It's a reference to one (or all) of the words in Linebuf.
*/
walk_tree(root->left);
if ( ival = popint() )
{
if ( ival > Fieldcount )
ival = Fieldcount;
else if ( ival < 1 )
ival = 1;
data.dptr = Fields[ ival-1 ];
}
else
{
/*
* Reconstitute the line buffer in case any of the
* fields have been changed.
*/
unparse( Fields, Fieldcount, Linebuf, Fieldsep );
data.dptr = Linebuf;
}
/*
* $<expr>'s are treated the same as string constants:
*/
push( (char) 1, (char) ACTUAL, (char) BYTE, &data );
break;
case T_UMINUS:
walk_tree(root->left);
pushint( - popint() );
break;
case T_STAR:
walk_tree(root->left);
/*
* If item on stack is an LVALUE, do an extra level of
* indirection before changing it to an LVALUE.
*/
if ( Stackptr->lvalue )
Stackptr->value.ptrptr =
(char **) *Stackptr->value.ptrptr;
Stackptr->lvalue = 1;
--Stackptr->class;
break;
case T_ADDROF:
walk_tree(root->left);
if ( Stackptr->lvalue )
Stackptr->lvalue = 0;
else
error( "'&' operator needs an lvalue", ACT_ERROR );
break;
case T_CONSTANT:
pushint(((DATUM *) (root->left))->ival);
break;
case T_FUNCTION:
function(((DATUM *) (root->left))->ival, root->right);
break;
case T_REGEXP:
/*
* Perform a match of the regular expression agains input
* line.
*/
unparse( Fields, Fieldcount, Linebuf, Fieldsep );
pushint( match( Linebuf, (char *) root->left ) );
break;
case T_REGEXP_ARG:
/*
* A regular expression that is to be passed as a function
* argument.
*/
data.dptr = (char *) root->left;
push( (char) 1, (char) ACTUAL, (char) BYTE, &data );
break;
case T_STRING:
data.dptr = (char *) root->left;
push( (char) 1, (char) ACTUAL, (char) BYTE, &data );
break;
case T_NF:
pushint( Fieldcount );
break;
case T_NR:
pushint( Recordcount );
break;
case T_FS:
data.dptr = Fieldsep;
push( (char) 1, (char) ACTUAL, (char) BYTE, &data );
break;
case T_RS:
data.dptr = Recordsep;
push( (char) 1, (char) ACTUAL, (char) BYTE, &data );
break;
case T_FILENAME:
data.dptr = Filename;
push( (char) 1, (char) ACTUAL, (char) BYTE, &data );
break;
case T_VARIABLE:
pvar = (VARIABLE *) root->left;
/*
* it's a plain variable. The way a variable is
* represented on the stack depends on its type:
* lvalue class value.dptr
* vars: 1 0 address of var
* ptrs: 1 1 ptr to address of ptr
* array: 0 1 address of var
*/
if ( pvar->vclass && !pvar->vlen )
/* it's a pointer */
data.dptr = (char *) &pvar->vptr;
else
/* an array or simple variable */
data.dptr = pvar->vptr;
/*
* If it's an array it can't be used as an LVALUE.
*/
push( pvar->vclass, (char) !pvar->vlen, pvar->vsize, &data );
break;
case T_LBRACKET:
walk_tree(root->left);
if ( ! Stackptr->class )
error( "'[]' needs an array or pointer", ACT_ERROR );
/*
* compute the subscript
*/
walk_tree(root->right);
ival = popint();
/*
* compute the offset (subscript times WORD for int arrays)
* and then the effective address.
*/
ival *= Stackptr->size;
if ( Stackptr->lvalue )
/*
* It's a pointer - don't forget that the stack top
* item's value is the address of the pointer so we
* must do another level of indirection.
*/
Stackptr->value.dptr = *Stackptr->value.ptrptr+ival;
else
/*
* It's a plain array - the stack top item's value is
* the address of the first element in the array.
*/
Stackptr->value.dptr += ival;
/*
* The stack top item now becomes an LVALUE, but we've
* reduced the indirection level.
*/
Stackptr->lvalue = 1;
--Stackptr->class;
break;
case T_POSTINCR:
walk_tree(root->left);
postincdec(1);
break;
case T_POSTDECR:
walk_tree(root->left);
postincdec(-1);
break;
case T_STATEMENT:
if(root->left) {
walk_tree(root->left);
if(pop_array[root->left->operator])
popint();
}
walk_tree(root->right);
break;
case T_DECLARE:
pdecl = (VARDECL *) root->left;
pvar = pdecl->variable;
if(pdecl->vsize != ((pvar->vlen ? pvar->vlen : 1)*
pvar->vsize)) {
/*
* The amount of storage needed for the variable has
* changed.
*/
free(pvar->vptr);
pvar->vptr = get_clear_memory(pdecl->vsize);
}
pvar->vclass = pdecl->vclass;
pvar->vsize = pdecl->vsize;
pvar->vlen = 0;
walk_tree(root->right);
break;
case T_ARRAY_DECLARE:
/* Compute the dimension */
walk_tree(root->left->right);
ival = popint();
pdecl = (VARDECL *) root->left->left;
pvar = pdecl->variable;
if((ival*pdecl->vsize) != ((pvar->vlen ? pvar->vlen : 1)*
pvar->vsize)) {
free(pvar->vptr);
pvar->vptr = get_clear_memory(ival*pdecl->vsize);
}
pvar->vclass = pdecl->vclass;
pvar->vsize = pdecl->vsize;
pvar->vlen = ival;
walk_tree(root->right);
break;
case T_IF:
walk_tree(root->left->left);
if(popint())
walk_tree(root->left->right);
else
walk_tree(root->right);
break;
case T_WHILE:
while( !Saw_break )
{
walk_tree(root->left);
if( ! popint() )
break;
walk_tree(root->right);
}
Saw_break = 0;
break;
case T_BREAK:
Saw_break = 1;
break;
default:
DBUG_PRINT("walk_tree",
("decimal value of operator = %d",root->operator));
error("internal error: parse tree node with unknown symbol",
ACT_ERROR);
}
DBUG_VOID_RETURN;
}
void preincdec(incr)
register int incr;
{
/*
* Pre increment/decrement
*/
DBUG_ENTER("preincdec");
if ( Stackptr->lvalue )
{
if ( Stackptr->class )
incr *= Stackptr->size;
*Stackptr->value.ptrptr += incr;
}
else
error( "pre '++' or '--' needs an lvalue", ACT_ERROR );
DBUG_VOID_RETURN;
}
void postincdec(incr)
register int incr;
{
/*
* Post increment/decrement
*/
register char **pp;
DBUG_ENTER("postincdec");
if ( Stackptr->lvalue )
{
if ( Stackptr->class )
{
/*
* It's a pointer - save its old value then
* increment/decrement the pointer. This makes the
* item on top of the stack look like an array, which
* means it can no longer be used as an LVALUE. This
* doesn't really hurt, since it doesn't make much
* sense to say:
* char *cp;
* cp++ = value;
*/
pp = (char **) *Stackptr->value.ptrptr;
*Stackptr->value.ptrptr += incr * Stackptr->size;
Stackptr->value.ptrptr = pp;
}
else
{
/*
* It's a simple variable - save its old value then
* increment/decrement the variable. This makes the
* item on top of the stack look like a constant,
* which means it can no longer be used as an LVALUE.
* Same reasoning as above.
*/
if ( Stackptr->size == BYTE )
pp = (char **) *Stackptr->value.dptr;
else
pp = (char **) *Stackptr->value.ptrptr;
*Stackptr->value.ptrptr += incr;
Stackptr->value.ptrptr = pp;
}
Stackptr->lvalue = 0;
}
else
error( "post '++' or '--' needs an lvalue", ACT_ERROR );
DBUG_VOID_RETURN;
}